package se.webbzon.boltzmann.game.object.player.boltzmann;

import se.webbzon.boltzmann.effect.FireBombEffect;
import se.webbzon.boltzmann.effect.LargeExplosionEffect;
import se.webbzon.boltzmann.game.character.CharacterFacing;
import se.webbzon.boltzmann.game.object.camera.GameCamera;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.boltzmann.timer.Timer;
import se.webbzon.boltzmann.timer.TimerListener;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldMovableObject;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.EllipsoidAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;

public class FireBomb extends WorldMovableObject {
	
	// The maximal radius for the fire bomb
	private static final double maxRadius = 24;
	
	// The maximal time between hurling and explosion
	private static final int maxDuration = 15;
	
	// The game camera associated with this fire bomb
	private final GameCamera camera;
	
	// The Boltzmann character associated with this fire bomb
	private final BoltzmannPlayerCharacter boltzmann;
	
	// The time (number of steps) since creation
	private int t;
	
	// The radius of the fire bomb
	private double radius;
	
	// The remaining time (in number of steps) for the fire bomb.
	// If the remaining time is negative then the fire bomb has not
	// yet been hurled. 
	private int remaining;
	
	/*============================================================
	Constructors
	============================================================*/

	public FireBomb(BoltzmannPlayerCharacter boltzmann, GameCamera camera) {
		super(	WorldObject.onCreate + WorldObject.onStep + WorldObject.onDestroy, 
				createAppearance());
		this.boltzmann = boltzmann;
		this.camera = camera;
		remaining = -1;
		t = 0;
		
		setSize(1,1,1);
		final double xOffset;
		if (	boltzmann.getFacing() == CharacterFacing.LEFT_DOWN ||
				boltzmann.getFacing() == CharacterFacing.LEFT_UP)
			xOffset = -36;
		else
			xOffset = 36;
		setPosition(boltzmann.getX() + xOffset,boltzmann.getY(),boltzmann.getZ());
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Hurls the fire bomb in the direction faced by boltzmann. **/
	public void hurl() {
		camera.setTarget(this);
		camera.resetHover();
		remaining = maxDuration;
		if (	boltzmann.getFacing() == CharacterFacing.LEFT_DOWN ||
				boltzmann.getFacing() == CharacterFacing.LEFT_UP)
			setVelocity(-12,0,0);
		else
			setVelocity(12,0,0);
	}
	
	@Override public void onCreate(WorldArea world) {
		camera.setHover(32, 256);
	}
	
	@Override public void onStep(WorldArea world) {
		t ++;
		if (remaining < 0) {
			final double focus = boltzmann.getFocus();
			radius = maxRadius * (focus + 0.1 * (1 + Math.cos(30*focus)));
			setSize(radius,radius,radius);
			final double angle = t * 0.1;
			setRotation(1,Math.sin(angle),Math.cos(angle),angle);
		} else if (remaining == 0) {
			world.destroyInstance(this);
		} else
			remaining--;
	}
	
	@Override public void onDestroy(WorldArea world) {
		final double maxRadius = radius * 0.75;
		final int particles = (int) radius / 2;
		for (int i = 0; i < particles; i++)
			new FireBombEffect(this,maxRadius).launch(world);
		new LargeExplosionEffect(this).launch(world);
	
		Timer timer = new Timer(30);
		timer.addListener(new TimerListenerImpl());
		timer.start(world);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	private static final Appearance3D createAppearance() {
		SimpleAppearance3D appearance = new EllipsoidAppearance3D();
		appearance.setTextureSet(Resources.getTextureSet("effect_lava"));
		return appearance;
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of a timer listener. **/
	private final class TimerListenerImpl implements TimerListener {

		@Override public void onAlarm(Timer timer, WorldArea world) {
			camera.setTarget(boltzmann);
		}
		
	}

}
